#This file contains ALL the functions of dealing interrupt.
#                                                     ---HalfGod(ChenWu)  2012-02-02 21:25:28 
.global   DivideError_Fault
.global   Debug_FaultTrap
.global   NMI_Interrupt
.global   Breakpoint_Trap
.global   Overflow_Trap
.global   BoundsCheck_Fault
.global   InvalidOpcode_Fault
.global   DeviceNotAvailable_Fault
.global   DoubleFault_Abort
.global   CoprocessorSegmentOverrun_Fault
.global   InvalidTSS_Fault
.global   SegmentNotPresent_Fault
.global   StackSegment_Fault
.global   GeneralProtection_Fault
.global   PageFault_Fault
.global   ReservedInterrupt_NotUsed
.global   CoprocessorError_Fault
.global   AlignmentCheck_Fault
.global   MachineCheck_Abort
.global   SIMDFloatingPointException_Fault

.global   UselessInterruptHandler

.global Master8259A_Timer
.global Master8259A_Keyboard
.global Master8259A_SerialPort2
.global Master8259A_SerialPort1
.global Master8259A_LPT2
.global Master8259A_Floppy
.global Master8259A_LPT1
.global Slave8259A_RealtimeTimer
.global Slave8259A_Redirect
.global Slave8259A_Reserved1
.global Slave8259A_Reserved2
.global Slave8259A_PS2Mouse
.global Slave8259A_FPUException
.global Slave8259A_ATA
.global Slave8259A_Reserved3

.global System_Call

.global Restart

.extern ReenterKernel

.extern ATA_Interrupt

.extern Keyboard_Interrupt

.extern   __System_Call__
#the following function is in arc/386/init/kernelinit.c
.extern   IntelRerservedExceptionHandler
#the following function is in kernel/schedule/schedule.c
.extern   Schedule
.extern   tss
.extern   WhoRunning
.equ      PaddingErrorCode   ,  0xFFFFFFFF
#the kernel interrupt stack size is 16KB
.equ      InterruptStackTop     ,  0x100000+0x4000

.section .text


DivideError_Fault:
   pushl  $PaddingErrorCode
   pushl  $0
   jmp    Exception0_19Handler

Debug_FaultTrap:
   pushl  $PaddingErrorCode
   pushl  $1
   jmp    Exception0_19Handler

NMI_Interrupt:
   pushl  $PaddingErrorCode
   pushl  $2
   jmp    Exception0_19Handler

Breakpoint_Trap:
   pushl  $PaddingErrorCode
   pushl  $3
   jmp    Exception0_19Handler

Overflow_Trap:
   pushl  $PaddingErrorCode
   pushl  $4
   jmp    Exception0_19Handler

BoundsCheck_Fault:
   pushl  $PaddingErrorCode
   pushl  $5
   jmp    Exception0_19Handler

InvalidOpcode_Fault:
   pushl  $PaddingErrorCode
   pushl  $6
   jmp    Exception0_19Handler

DeviceNotAvailable_Fault:
   pushl  $PaddingErrorCode
   pushl  $7
   jmp    Exception0_19Handler

DoubleFault_Abort:
   pushl  $8
   jmp    Exception0_19Handler

CoprocessorSegmentOverrun_Fault:
   pushl  $PaddingErrorCode
   pushl  $9
   jmp    Exception0_19Handler

InvalidTSS_Fault:
   pushl  $10
   jmp    Exception0_19Handler

SegmentNotPresent_Fault:
   pushl  $11
   jmp    Exception0_19Handler

StackSegment_Fault:
   pushl  $12
   jmp    Exception0_19Handler

GeneralProtection_Fault:
   pushl  $13
   jmp    Exception0_19Handler

PageFault_Fault:
   pushl  $14
   jmp    Exception0_19Handler

ReservedInterrupt_NotUsed:
   pushl  $PaddingErrorCode
   pushl  $15
   jmp    Exception0_19Handler

CoprocessorError_Fault:
   pushl  $PaddingErrorCode
   pushl  $16
   jmp    Exception0_19Handler

AlignmentCheck_Fault:
   pushl  $17
   jmp    Exception0_19Handler

MachineCheck_Abort:
   pushl  $PaddingErrorCode
   pushl  $18
   jmp    Exception0_19Handler

SIMDFloatingPointException_Fault:
   pushl  $PaddingErrorCode
   pushl  $19
   jmp    Exception0_19Handler

Exception0_19Handler:
   call  IntelInterruptHandler
   addl  $8,%esp
   iret

UselessInterruptHandler:
   iret

Master8259A_Timer:
   subl   $4,%esp
 
   pushl  %edi
   pushl  %esi
   pushl  %ebp
   pushl  %esp
   pushl  %ebx
   pushl  %edx
   pushl  %ecx
   pushl  %eax

   movl   $tss,%eax
   movl   8(%eax),%ebx
   pushl  %ebx
   movl   4(%eax),%ebx
   pushl  %ebx

   movl   %cr0,%eax   
   pushl  %eax
   movl   %cr3,%eax
   pushl  %eax
   pushw  %es
   pushw  %ds
   pushw  %fs
   pushw  %gs
    #  movl   %eax,temp
#   movl   WhoRunning , %eax
 #  cmpl    $0xA00000,%esp
   # je  .
 #  movl   temp,%eax
  
   movw   %ss,%ax
   movw   %ax,%ds
   movw   %ax,%es
   
  
   movb   $0x20,%al
   outb   %al,$0x20
  
   incl   ReenterKernel
   cmpl   $0,ReenterKernel
   jne    RestartReenter
   movl   $InterruptStackTop,%esp
   pushl  $Restart
   movl  %cr0,%edi
   andl  $0x7FFFFFFF,%edi
   movl  %edi,%cr0
   sti
   call   Schedule
   cli
   ret

Master8259A_Keyboard:
   subl   $4,%esp
 
   pushl  %edi
   pushl  %esi
   pushl  %ebp
   pushl  %esp
   pushl  %ebx
   pushl  %edx
   pushl  %ecx
   pushl  %eax

   movl   %eax,%esi
   movl   %ebx,%edi
   movl   $tss,%eax
   movl   8(%eax),%ebx
   pushl  %ebx
   movl   4(%eax),%ebx
   pushl  %ebx

   movl   %cr0,%eax   
   pushl  %eax
   movl   %cr3,%eax
   pushl  %eax
   movl   %esi,%eax
   movl   %edi,%ebx

   pushw  %es
   pushw  %ds
   pushw  %fs
   pushw  %gs
   
   movw   %ss,%ax
   movw   %ax,%ds
   movw   %ax,%es

#Resume the interrupt
   movb   $0x20,%al
   outb   %al,$0x20
   nop 
   outb   %al,$0xA0


   incl   ReenterKernel
   cmpl   $0,ReenterKernel
   jne    LABEL_KEYBOARD_REENTER
   movl   $InterruptStackTop,%esp
   pushl  $Restart
   jmp    LABEL_KEYBOARD_HANDLER
LABEL_KEYBOARD_REENTER:
   pushl  $RestartReenter
LABEL_KEYBOARD_HANDLER:
   movl  %cr0,%edi
   andl  $0x7FFFFFFF,%edi
   movl  %edi,%cr0
   sti
   call   Keyboard_Interrupt
   cli
   ret

Master8259A_SerialPort2:
   iret

Master8259A_SerialPort1:
   iret

Master8259A_LPT2:
   iret

Master8259A_Floppy:
   iret

Master8259A_LPT1:
   iret

Slave8259A_RealtimeTimer:
   iret

Slave8259A_Redirect:
   iret

Slave8259A_Reserved1:
   iret

Slave8259A_Reserved2:
   iret

Slave8259A_PS2Mouse:
   iret

Slave8259A_FPUException:
   iret

Slave8259A_ATA:
   subl   $4,%esp
 
   pushl  %edi
   pushl  %esi
   pushl  %ebp
   pushl  %esp
   pushl  %ebx
   pushl  %edx
   pushl  %ecx
   pushl  %eax

   movl   %eax,%esi
   movl   %ebx,%edi
   movl   $tss,%eax
   movl   8(%eax),%ebx
   pushl  %ebx
   movl   4(%eax),%ebx
   pushl  %ebx

   movl   %cr0,%eax   
   pushl  %eax
   movl   %cr3,%eax
   pushl  %eax
   movl   %esi,%eax
   movl   %edi,%ebx

   pushw  %es
   pushw  %ds
   pushw  %fs
   pushw  %gs
   
  
   

   movw   %ss,%ax
   movw   %ax,%ds
   movw   %ax,%es

#Resume the ATA interrupt
   movb   $0x20,%al
   outb   %al,$0x20
   nop 
   outb   %al,$0xA0


   incl   ReenterKernel
   cmpl   $0,ReenterKernel
   jne    LABEL_ATA_REENTER
   movl   $InterruptStackTop,%esp
   pushl  $Restart
   jmp    LABEL_ATA_HANDLER
LABEL_ATA_REENTER:
   pushl  $RestartReenter
LABEL_ATA_HANDLER:
   movl  %cr0,%edi
   andl  $0x7FFFFFFF,%edi
   movl  %edi,%cr0
   sti
   call   ATA_Interrupt
   cli
   ret

Slave8259A_Reserved3:
   iret

System_Call:
   subl   $4,%esp
 
   pushl  %edi
   pushl  %esi
   pushl  %ebp
   pushl  %esp
   pushl  %ebx
   pushl  %edx
   pushl  %ecx
   pushl  %eax

   movl   %eax,%esi
   movl   %ebx,%edi
   movl   $tss,%eax
   movl   8(%eax),%ebx
   pushl  %ebx
   movl   4(%eax),%ebx
   pushl  %ebx

   movl   %cr0,%eax   
   pushl  %eax
   movl   %cr3,%eax
   pushl  %eax
   movl   %esi,%eax
   movl   %edi,%ebx

   pushw  %es
   pushw  %ds
   pushw  %fs
   pushw  %gs
   
  
   
   movl   %eax,%esi
   movw   %ss,%ax
   movw   %ax,%ds
   movw   %ax,%es
  
   movl   %esi,%eax
  

   incl   ReenterKernel
   cmpl   $0,ReenterKernel
   jne    LABEL_SYSTEMCALL_REENTER
   movl   $InterruptStackTop,%esp
   pushl  $Restart
   jmp    LABEL_SYSTEMCALL_HANDLER
LABEL_SYSTEMCALL_REENTER:
   pushl  $RestartReenter
LABEL_SYSTEMCALL_HANDLER:
   
   pushl %edx
   pushl %ecx
   pushl %ebx
   pushl %eax
   movl  %cr0,%edi
   andl  $0x7FFFFFFF,%edi
   movl  %edi,%cr0
   sti
   call   __System_Call__
   cli
   addl  $0x10,%esp
   
   ret


Restart:
   movl   WhoRunning , %esp
   


RestartReenter:
   decl   ReenterKernel
   popw   %gs
   popw   %fs
   popw   %ds
   popw   %es
   popl   %eax
   movl   %eax,%cr3
   popl   %eax
   movl   %eax,%cr0

   popl   %eax
   movl   $tss,%ebx
   movl   %eax,4(%ebx)
   popl   %eax
   movl   %eax,8(%ebx)

   

   popl   %eax
   popl   %ecx
   popl   %edx
   popl   %ebx
 
#   popl   %esp       this sentence is just for the "popad" ,which i found can't used in gas
   addl   $4 ,%esp
   popl   %ebp
   popl   %esi
   popl   %edi
   addl   $4,%esp

 #  movl   %eax,temp
#   movl   WhoRunning , %eax
 #  cmp    $0xA00000,%eax
 #  je  .
 #  movl   temp,%eax

   iret
#temp: .4byte 0
